package com.example.activiti6_demo.service;

import com.example.activiti6_demo.mapper.ActRetMapper;
import org.activiti.bpmn.model.FlowElement;
import org.activiti.engine.HistoryService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.history.HistoricActivityInstance;
import org.activiti.engine.history.HistoricActivityInstanceQuery;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.history.HistoricVariableInstance;
import org.activiti.engine.impl.persistence.entity.*;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @des: 输入类描述
 * @Author: mengxiangzhong
 * @Date: 2022/10/14 21:44
 **/
@Service
public class actService {

    @Resource
    HistoryService  historyService;

    @Resource
    RepositoryService repositoryService;


    @Resource
    ActRetMapper actMapper;



    @Value("${act.dataType:mysql}")
    String dataSourceType;



    @Transactional
    public void revoke(String pid,String taskName) throws Exception {
        Boolean isMysql = dataSourceType.equals("mysql");
        if(isMysql){
            actMapper.stopMysqlFerKey();
        }else {
            actMapper.stopPgsqlFerKey();
        }

        // 1.找到taskId，下面选取符合的assignee可以直接在query中筛选同businessId
        List<HistoricTaskInstance> htiList = historyService.createHistoricTaskInstanceQuery()
                .processInstanceId(pid)
                .orderByTaskCreateTime()
                .desc()
                .list();
        if(CollectionUtils.isEmpty(htiList)){
            throw new RuntimeException("该实例ID不存在");
        }

        HistoricTaskInstance myTask = null;
        if(taskName != null && taskName.trim().length() != 0){
            for(HistoricTaskInstance h : htiList){
                if(h.getName().equals(taskName)){
                    myTask = h;
                    break;
                }
            }
        }
        if(myTask == null){
            myTask = htiList.get(0);
        }


        // 2.创建execution
        // 获取当前节点对象，塞到executionEntity中
        FlowElement flowElement = repositoryService.getBpmnModel(myTask.getProcessDefinitionId()).getMainProcess().getFlowElement(myTask.getTaskDefinitionKey());
        ExecutionEntityImpl executionEntity = new ExecutionEntityImpl();
        executionEntity.setId(myTask.getExecutionId());
        executionEntity.setProcessInstanceId(myTask.getProcessInstanceId());
        executionEntity.setProcessDefinitionId(myTask.getProcessDefinitionId());
        executionEntity.setParentId(myTask.getProcessInstanceId());
        executionEntity.setRootProcessInstanceId(myTask.getProcessInstanceId());
        executionEntity.setCurrentFlowElement(flowElement);
        executionEntity.setStartTime(new Date());
        // 子execution分支的is_scope的值为0，主分支的为1。这里一定要设置，否则只能暂时退回，再走一个节点该execution就会被删除
        executionEntity.setScope(false);
        executionEntity.setActive(true);

        /* mapper对象的sql可以写对应表的增删改查，
         */
        int ie = actMapper.insertExecution(executionEntity);
        if ( ie == 1) {
            System.out.println("新添execution成功，id="+myTask.getExecutionId());
        }
        /* task的assignee字段其他的ru_task没有，我也没有加
         */

        // 3.insert task into ACT_RU_TASK
        TaskEntityImpl runTask = new TaskEntityImpl();
        runTask.setId(myTask.getId());
        runTask.setName(myTask.getName());
        runTask.setPriority(myTask.getPriority());
        //runTask.setAssignee(myTask.getAssignee());
        runTask.setCreateTime(new Date());
        runTask.setExecutionId(myTask.getExecutionId());
        runTask.setProcessInstanceId(myTask.getProcessInstanceId());
        runTask.setProcessDefinitionId(myTask.getProcessDefinitionId());
        runTask.setTaskDefinitionKey(myTask.getTaskDefinitionKey());
        int it = actMapper.insertTask(runTask);
        if( it == 1) {
            System.err.println("新添task成功，id={}"+myTask.getId());
        }
        /* identityLink只需要添加该任务的一条记录，用taskId筛选即可
         */
        // 4.insert task identitylink into ACT_RUN_IDENTITYLINK
        List<HistoricIdentityLinkEntityImpl> historicIdentityLinkEntities = actMapper.selectHistoricIdentityLinksByProcessInstanceAndTaskId(myTask.getProcessInstanceId(),myTask.getId());
        for ( HistoricIdentityLinkEntity e: historicIdentityLinkEntities) {
            if (e.getTaskId() != null && e.getTaskId().equals(myTask.getId())) {
                IdentityLinkEntityImpl identityLink = new IdentityLinkEntityImpl();
                identityLink.setId(e.getId());
                identityLink.setType(e.getType());
                identityLink.setUserId(e.getUserId());
                identityLink.setGroupId(e.getGroupId());
                identityLink.setTaskId(e.getTaskId());
                identityLink.setProcessInstanceId(e.getProcessInstanceId());
                actMapper.insertIdentityLink(identityLink);

            }
        }
        /* 这里的variable根据情况加一条审批相关的变量，可能不用加；加了话需要注意子流程审批用到的变量是什么语句查询的，有executionId和taskId的条件话就按条件给字段赋值。推节点时如果查不到会报无法解析表达式异常
         */
        // 5.insert variables into ACT_RU_VARIABLE
        List<HistoricVariableInstance> historicVariableInstances = historyService.createHistoricVariableInstanceQuery().executionId(myTask.getExecutionId()).list();
        List<VariableInstanceEntity> variables = new ArrayList<>();
        for (HistoricVariableInstance e : historicVariableInstances) {
            if ("result".equals(e.getVariableName())) {
                VariableInstanceEntityImpl v = new VariableInstanceEntityImpl();
                v.setName(e.getVariableName());
                v.setId(e.getId());
                v.setTypeName(e.getVariableTypeName());
                v.setExecutionId(myTask.getExecutionId());
                v.setProcessInstanceId(e.getProcessInstanceId());
                v.setTextValue(String.valueOf(e.getValue()));
                variables.add(v);
                break;
            }
        }
        if(!CollectionUtils.isEmpty(variables)){
            int ih = actMapper.bulkInsertVariableInstance(variables);
            if(ih > 0){
                System.out.println("插入流程变量成功");
            }
        }

        // 6. task历史表
        // -----1 置空当前步骤
        HistoricTaskInstanceEntityImpl hstTaskUpdate = new HistoricTaskInstanceEntityImpl();
        hstTaskUpdate.setId(myTask.getId());
        hstTaskUpdate.setProcessDefinitionId(myTask.getProcessDefinitionId());
        hstTaskUpdate.setTaskDefinitionKey(myTask.getTaskDefinitionKey());
        hstTaskUpdate.setProcessInstanceId(myTask.getProcessInstanceId());
        hstTaskUpdate.setExecutionId(myTask.getExecutionId());
        hstTaskUpdate.setName(myTask.getName());
        hstTaskUpdate.setAssignee(myTask.getAssignee());
        hstTaskUpdate.setStartTime(myTask.getStartTime());
        hstTaskUpdate.setClaimTime(myTask.getClaimTime());
        hstTaskUpdate.setEndTime(null);
        hstTaskUpdate.setDueDate(myTask.getDueDate());
        hstTaskUpdate.setDeleteReason(myTask.getDeleteReason());
        hstTaskUpdate.setPriority(myTask.getPriority());
        actMapper.updateHistoricTaskInstance(hstTaskUpdate);
        // ------2删除后续步骤
        List<String> deleteTaskIdList = new ArrayList<>();
        for(HistoricTaskInstance h : htiList){
            if(Long.parseLong(h.getId()) > Long.parseLong(myTask.getId())){
                deleteTaskIdList.add(h.getId());
            }
        }
        if(!CollectionUtils.isEmpty(deleteTaskIdList)){
            actMapper.deleteHistoricTask(deleteTaskIdList);
        }

        //7.历史节点表
        List<HistoricActivityInstance>   nodeList = historyService.createHistoricActivityInstanceQuery() .processInstanceId(pid)
               .orderByHistoricActivityInstanceStartTime()
                .desc()
                .list();

        HistoricActivityInstance  nowAct = null;

        // --1 删除后续步骤
        List<String> deleteNodeIdList = new ArrayList<>();
        for(HistoricActivityInstance h : nodeList){

            if(h.getTaskId() != null && h.getTaskId().length() != 0 &&
                    h.getTaskId().equals(myTask.getId())){
                nowAct = h;
            }
            if(h.getTaskId() != null && h.getTaskId().length() != 0 &&
                    Long.parseLong(h.getTaskId()) > Long.parseLong(h.getTaskId())){
                deleteNodeIdList.add(h.getId());
                continue;
            }
            if(h.getActivityType().equals("endEvent")){
                deleteNodeIdList.add(h.getId());
            }
        }
        if(!CollectionUtils.isEmpty(deleteNodeIdList)){
            actMapper.deleteHistoricAct(deleteNodeIdList);
        }

        //---2 修改
        if(nowAct != null){
            actMapper.resetHistoricAct(nowAct.getId());
        }


        if(isMysql){
            actMapper.startMysqlFerkey();
        }else {
            actMapper.startPgsqlFerkey();
        }
    }

}
